home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / anidone / 3ddemo / matricks.doc < prev    next >
Text File  |  1995-05-02  |  28KB  |  583 lines

  1.  
  2.                   Documentation for the graphic functions.
  3.                   ----------------------------------------
  4.  
  5.                      sources and doc by L.J.M. de Wit
  6.  
  7.       OBJECTIVE
  8.  
  9.    The purpose was to supply a number of useful graphic functions that
  10.    can be used in a modest scale for animation, 3D motion, demo's. Another
  11.    purpose was to poke up some discussion conceirning graphic functions,
  12.    representations, etc. I'm only in a minor way involved with graphics in
  13.    my job, so I'm open for any other ideas. The functions offered have not
  14.    the least pretention to be exhaustive, although it would be nice to
  15.    enlarge and enrich the capabilities in future releases. Whoever has ideas,
  16.    remarks, bugs found in the package, questions about the source or how to
  17.    use it, is invited to send them to me; any help is welcome but also gladly
  18.    offered.
  19.  
  20.  
  21.       COPYRIGHT AND THE LIKE
  22.  
  23.    The source can be used freely for non-commercial purposes;
  24.    if you redistribute the source keep my copyright notice in; that's a small
  25.    fee for the effort I've put into it. If you plan to make changes to the
  26.    source and distribute I would like to know; this to prevent duplication of
  27.    effort, and existance of different branches; perhaps redistribution could
  28.    go via me (maybe I'm already too optimistic about others willing to work
  29.    on some part of the code 8-). Also anyone planning to use (part of) it in
  30.    a commercial product should contact me; this be said to keep everyone
  31.    interested! 8-).
  32.  
  33.  
  34.       TARGET MACHINES, LANGUAGE USED
  35.  
  36.    In the present form the demo program runs on Atari STs (1 Meg required).
  37.    The amount of memory is merely required to run the demo that stores a
  38.    series of compressed images; this is the only part that really requires
  39.    memory. It should not be hard to port the code to various machines, notably
  40.    the Mac, the Amiga, the IBM PC with graphics card, a Sun, etc.
  41.    The language used is C; a small part of the code is in 68000 assembler.
  42.    Since this code also has a line drawing routine (for bit mapped display)
  43.    it can even be used on systems with a very limited or no graphics library.
  44.  
  45.  
  46.       BREAK UP OF SOURCES
  47.  
  48.    Currently the following source modules exist:
  49.  
  50.       matricks.h:    header file for extern declarations and the like.
  51.       3demo.c:       contains main and all demo functions
  52.       mat.c:         operations on matrices
  53.       object.c:      operations on objects: items and instances
  54.       gemfuncs.c:    O.S. dependant part of graphic functions: opening a work-
  55.                      station, swapping screen memory etc.
  56.       mxops.asm:     like mat.c but these are assembler functions.
  57.       drawlin.asm:   function to draw a line.
  58.  
  59.    The last 3 named are the ones most likely to cause problems when porting.
  60.    If your system doesn't have GEM, gemfuncs.c will have to be rewritten,
  61.    but this is no big deal; if your system uses an other processor than a
  62.    68000 the assembler functions will have to be re-created; also if the
  63.    layout of your bitmap display is different from (any of the) Atari ST,
  64.    the drawlin.asm needs a thorough scan.
  65.  
  66.  
  67.       IDEAS ABOUT REPRESENTATIONS ETC.
  68.  
  69.    In order to give you a better understanding of the source I'll explain
  70.    some of the ideas used in the code and why some choices were made.
  71.       1) Use of matrices for all motions (translation, rotation and any
  72.    combination of these). An object in space can be represented by a set
  73.    of coordinates for each point; if the object consists of a set of lines
  74.    it suffices to store the coordinates of the end points and the way the
  75.    points are connected (the polygons). The coordinates of an object are
  76.    stored per row for each point in a 2D array (the height equals the
  77.    number of points registrated, the width the number of coordinates: 4).
  78.    A motion of the object can now be computed by multiplying the (npoints x 4)
  79.    coordinate array with the (4 x 4) transformation array, resulting in a
  80.    new (npoints x 4) array, representing the new coordinates. Note that in
  81.    case a combination of transformations is applied to the object (e.g.
  82.    a translation followed by a rotation) it is cheaper (in terms of # of
  83.    multiplications) to first multiply the (4 x 4) transformation matrices
  84.    (resulting in a new 4 x 4 matrix) and then multiply the coordinate matrix
  85.    with this one than to multiply the coordinate matrix with each
  86.    transformation matrix separately. This is also one of the reasons that
  87.    using matrix calculus is much cleaner and clearer than using goniometric
  88.    formulas; you do not get lost in long formulas and you can concentrate
  89.    on things that really matter, and the speed gain is vast when you're
  90.    handling several points / several transformations at a time.
  91.       2) Use of 3D projective coordinates to represent a point in 3D space.
  92.    Those interested in but not familiar with these coordinates are advised
  93.    to read an (introductory) book about Projective Geometry; for those that
  94.    are only not familiar with it (and thus not interested 8-), it should
  95.    suffice to say that a point's
  96.    coordinates may all be multiplied with a constant, so for instance
  97.    (1, 2, 5, 7) is the same point as (3, 6, 15, 21) and that the (normal)
  98.    Carthesian coordinate system can be embedded in projective space as
  99.    follows: if (X,Y,Z) is a point in 3D Carthesian it corresponds with
  100.    (X,Y,Z,1) in 3D projective space (note: 4 coordinates). Of course
  101.    you could choose (2.3X,2.3Y,2.3Z,2.3) also or any constant you like.
  102.    The two main advantages of using projective (or homogeneous) coordinates
  103.    that I can see are: a) all motions of a rigid body in space can be
  104.    represented by a matrix (or series of) multiplication(s), or, put
  105.    differently, each transformation can be represented by a matrix.
  106.    b) since homogeneous coordinates are used, the elements of the matrix
  107.    may be scaled with a constant factor. This is an important issue in
  108.    terms of speed, since it allows the use of integers throughout the code
  109.    (many architectures deal faster with integer calculations than float
  110.    and double calculations); yes, by using correctly chosen scaling factors
  111.    (not too small to retain precision, no too big to prevent overflow)
  112.    even shorts are usable (16 bits shorts that is). The 68000 handles
  113.    word (16 bit) multiplications as one instruction, resulting in fast
  114.    performed matrix multiplications. The result matrix is of course a
  115.    matrix with 32-bit elements, but these are scaled afterwards to fit again
  116.    in a short. In fact, the scaling chosen is such that multiplying these
  117.    shorts in pairs and adding 4 such pairs does not overflow a signed long.
  118.  
  119.  
  120.       ABOUT OBJECTS
  121.  
  122.    This being said and understood the notion of the objects used should be
  123.    easy now. Two types of objects are of special interest:
  124.    The item, in fact a pointer to a struct, defined by:
  125.  
  126.    typedef struct itstruct {  /* item definition: ptr to this struct */
  127.       int count;              /* # of points in this item */
  128.       polygon next;           /* pointer to polygon list */
  129.       WORD r_data[1][4];      /* homogene coordinates of first point; */
  130.    } *item;                   /* the rest follows hereafter */
  131.  
  132.    Note that only one row of the coordinate matrix is declared; this is to
  133.    allow for arbitrary sized arrays without having to resort to pointers
  134.    (of course the only reasonable usage must be by dynamic allocation of the
  135.    actual struct).
  136.    The 'polygon next' member is a pointer to a linked list of arrays of
  137.    indices, as follows:
  138.  
  139.    typedef struct polystruct {/* polygon def: ptr to this struct */
  140.       int count;              /* # of points in this polygon */
  141.       struct polystruct *next;/* ptr to next polygon */
  142.       WORD coord[1];          /* index of first point */
  143.    } *polygon;                /* the rest follows hereafter */
  144.  
  145.    Like with the item def. only one index is declared; in an actual case many
  146.    will follow in consecutive memory. Each polygon is a series of connected
  147.    lines, the indices being the numbers of the points in the coordinate array.
  148.    Thus an item can have several series of connected lines.
  149.  
  150.    An item is in fact a very static object, it can be seen as an abstraction.
  151.    If we want to use it, we need an other type of object, i.e. the instance.
  152.    An instance is also a pointer to a struct, defined by:
  153.  
  154.    typedef struct instruct {  /* instance def: ptr to this struct  */
  155.       item in_item;           /* item of which this is an instance */
  156.       WORD trans[4][4];       /* 4H that places it                 */
  157.       WORD i_data[1][2];      /* screen coordinates of first point */
  158.    } *instance;               /* the rest follows hereafter        */
  159.  
  160.    The 'item' member is the pointer to the corresponding item structure
  161.    (containing a coordinate array and a list of polygons).
  162.    The 'trans' member is the transformation matrix that puts the item in 3D
  163.    space (so its contents varies because it is multiplied each time by
  164.    whatever transformations act on the object).
  165.    To be able to do the calculation of projected points and actual drawing
  166.    of the computed lines in different places, there is also a storage area
  167.    in the instance structure that contains for each point the actual screen
  168.    coordinates (pixel coordinates). So it's written by the projection functions
  169.    and read by the draw functions. Again there's room for one point only,
  170.    but dynamic allocation 'over the edge of the struct' allows for an
  171.    arbitrary number of points. Note that the definition of C says that
  172.    consecutive members of the struct occupy consecutive places in memory, so
  173.    that we may safely use 'the other end' of the struct.
  174.  
  175.  
  176.       TERMINOLOGY USED
  177.  
  178.    To keep things small and simple the following abbreviations will be used:
  179.    4H: 4 x 4 homogeneous transformation (matrix). Unless stated otherwise,
  180.        this will be represented in the machine by a: short [4][4], where
  181.        short is a 16 bit wide integer.
  182.    I, O, IO: in, out, inout - for parameters.
  183.  
  184.       LIST OF FUNCTIONS AND BRIEF DISCUSSION
  185.  
  186.    Now follows a list of the functions offered and a tiny description of
  187.    them; consult the source if you want to go into detail, you will find
  188.    this text more or less also there. The functions from the 3demo.c module
  189.    are not listed here since they serve only a demonstration purpose and
  190.    are not suitable for general use.
  191.  
  192.    From mat.c:
  193.  
  194.    - note that, unless stated otherwise, memory for matrices etc. must
  195.      already exist, must be either dynamically or statically be allocated.
  196.  
  197.    o  void matapply(mat,func,v,fac)
  198.       WORD *mat;          IO the 4H to be transformed (e.g. ins->trans).
  199.       WORD *(*func)();    I  the kind of transformation, i.e. a function ptr.
  200.                              func can currently only be mattlate, matrotate,
  201.                              or matreflect.
  202.       double *v;          I  a 3D vector to quantisize the transformation.
  203.       double fac;         I  a number with which v is multiplied.
  204.  
  205.       Applies a transformation to a 4H. This can be a
  206.       translation, rotation or reflection. Matapply can typically be used
  207.       to create 4H's beforehand that represent a small motion (small
  208.       step in x-, y-, z - direction or turn around x-, y-, z - axis).
  209.       In that case mat is taken to be an 4H identity matrix, v one of the
  210.       unity vectors ((1,0,0), (0,1,0), (0,0,1)) and fac is a (small) number.
  211.  
  212.    o  void matcompose(a,b)
  213.       WORD *a;            IO
  214.       WORD *b;            I
  215.  
  216.       The result of the (homogeneous) multiplication of a and b is placed
  217.       into a. This function is implemented as a macro.
  218.       It can be used for instance to update an instance coordinate
  219.       transformation (take a to be ins->trans) when an other transformation
  220.       affects it (the b matrix).
  221.  
  222.    o  WORD *matident(n,a)
  223.       int n;              I
  224.       WORD *a;            O
  225.  
  226.       Create a nxn identity matrix and return the pointer to it.
  227.  
  228.    o  WORD *matreflect(v,a)
  229.       double *v;          I  a quantisizing 3D vector: the normal vector
  230.       WORD *a;            O  the 4H.
  231.  
  232.       Create a 4H reflection matrix. Used by matapply().
  233.  
  234.    o  WORD *matrotate(v,a)
  235.       double *v;          I  a quantisizing 3D vector: the rotation axis
  236.       WORD *a;            O  the 4H.
  237.  
  238.       Create a 4H rotation matrix.
  239.  
  240.    o  WORD *mattlate(v,a)
  241.       double *v;          I  a quantisizing 3D vector: the translation step
  242.       WORD *a;            O  the 4H.
  243.  
  244.       Create a 4H translation matrix.
  245.  
  246.    o  uchar *matscr_to_str(b_and_w)
  247.       bool b_and_w;       I  Use-only-black-and-white flag
  248.  
  249.       Compress screen into unsigned char array and return pointer to it.
  250.       If the flag is TRUE, the screen is handled as if only one colour was
  251.       present (even if it is multi-colour); this allows for some factors
  252.       extra compaction. The memory needed for the array is dynamically
  253.       allocated.
  254.       The screen information is stored in the following way:
  255.       Assume for simplicity's sake the screen consists of 200 lines, each
  256.       line being 160 bytes wide, so 160 (byte) columns wide (the peculiarities
  257.       of the different resolution and colours will be handled further on).
  258.       The first byte contains the number of nonempty columns that were found.
  259.       Then follows for each nonempty column:
  260.          the column number (0-159)
  261.          the number of line sets (0-80). A line set is a series of consecutive
  262.             nonzero bytes in one column.
  263.          Then follows for each line set:
  264.             the first line of the set (0-199).
  265.             the number of lines (0-199).
  266.             the actual values (each being 0-255)
  267.          until last line set in column
  268.       until last nonempty column on screen.
  269.       As for the different screen modes:
  270.          High res on the Atari has 400 lines, 80 byte columns. To be able
  271.          to deal with the lines from 256 up (the line no. must fit in a byte)
  272.          the lines from 200-399 are marked by using column numbers 160-239
  273.          (instead of 0-79) and line numbers 0-199 (instead of 200-399).
  274.          Medium and low res have both 200 lines. Medium has 80 columns,
  275.          2 colour bit planes, whereas low has 40 columns, 4 colour bit planes.
  276.          Because the colour info is stored as: word0 of plane0, word0 of
  277.          plane1, etc. the simple solution is to view an entire line as simply
  278.          160 bytes (of which there are overlapping pairs for medium and
  279.          overlapping quartets for low res.), so use columns 0-159.
  280.          The b_and_w flag simply says to ignore each odd word in medium res.
  281.          and each second, third and fourth word of four consecutive words in
  282.          low res. In this way, if the image was already black, a compaction
  283.          of 2 to 4 times above the existing compaction is reached.
  284.  
  285.    o  void matstr_to_scr(s,b_and_w)
  286.       register uchar *s;  I  Array of compressed data
  287.       bool b_and_w;       I  Handle-as-black-and-white-only flag
  288.  
  289.       Display compressed image. s should have been created by matscr_to_str().
  290.  
  291.    o  void error(func)
  292.       char *func;         I  name of function in which error occured
  293.  
  294.       Simple error handling function. Display a message and stop program.
  295.  
  296.    o  double maxfactor(arr,cnt)
  297.       double *arr;        I  the array
  298.       int cnt;            I  # elements in array
  299.  
  300.       Find maximal multiplication factor for an array of doubles so that each
  301.       array element after multiplication with this factor can be cast to
  302.       short without truncation.
  303.  
  304.    o  double mycos(a)
  305.       double a;           I
  306.  
  307.       Fast cosine function by table lookup. Each value that has been
  308.       calculated once can be retrieved by table lookup.
  309.  
  310.    o  double mysin(a)
  311.       double a;           I
  312.  
  313.       As mycos() for sine function.
  314.  
  315.    From mxops.asm:
  316.  
  317.    o  void mxhmul(a,b,c,p,q,r)                                                       *
  318.       short *a,           I  points to array of p x q shorts
  319.             *b,           I  points to array of q x r shorts
  320.             *c,           O  points to array of p x r shorts
  321.             p, q, r;
  322.  
  323.       Matrix multiplication for homogeneous coordinate matrices
  324.       c points to the result of the multiplication of the matrices
  325.       pointed to by a and b. It is scaled to fit in shorts.
  326.       Since a temporary array is used to store intermediate 32 bit
  327.       results c may be one of a, b without a problem.
  328.  
  329.    o  short *matcopy(a,b,n)
  330.       short *a;           I
  331.       short *b;           O
  332.       short n;            I
  333.  
  334.       Copy over n shorts from the array pointed to by a to that pointed
  335.       to by b.
  336.  
  337.    o  void mxproj(inarr,outarr,pcount,eye_z,scal_x,scal_y)
  338.       short *inarr,       I
  339.             *outarr;      O
  340.       short pcount;       I
  341.       short eye_z,        I  distance of observer to screen
  342.             scal_x,       I  scaling along x axis of screen
  343.             scal_y;       I  scaling along y axis of screen
  344.  
  345.       Projection of inarr onto the instance's screen coordinates outarr.
  346.       inarr points to an pcount x 4 array of shorts representing the hom.
  347.       coordinates of the pcount points of the instance.
  348.       outarr points to a pcount x 2 array of shorts representing the screen
  349.       coordinates to be calculated for each point (this array is part of the
  350.       instance).
  351.       eye_z, scal_x and scal_y are parameters that determine the projection.
  352.  
  353.    From gemfuncs.c:
  354.  
  355.    o  void gem_init()
  356.  
  357.       opens a virtual workstation and allocates extra screen memory for
  358.       smooth drawing.
  359.  
  360.    o  void gem_exit()
  361.  
  362.       closes a virtual workstation, restores screen location and exits.
  363.       The allocated memory for a screen is automatically returned to the
  364.       system.
  365.  
  366.    o  void swapscreen()
  367.  
  368.       switches the logical and physical screens. All drawing functions
  369.       (including displaying text) takes place on the logical screen, while
  370.       the physical screen is displayed. When the drawing is finished, the
  371.       pointers to the two screen areas are swapped. The VBL (vertical blank
  372.       interrupt routine) checks whether the physical screen pointer has
  373.       changed and if so, tells it the hardware. By altering the physical
  374.       screen location just before the screen is displayed (the beam is aimed
  375.       again at the start of the display it is ensured that movement is smooth
  376.       (no screen memory updating while is it being read).
  377.  
  378.    From drawlin.asm:
  379.  
  380.    o  void drawlin(x1,xy1,x2,y2)
  381.       WORD x1,y1,x2,y2;   I
  382.  
  383.       Draw a line between points (x1,y1) and (x2,y2) in high, medium or low
  384.       resolution. No attempt has been made to handle colours, different line
  385.       styles/widths, clipping, although this should be simple - maybe
  386.       something for a next release.
  387.       The method used for calculating the pixel coordinates of the line is
  388.       Bresenham's algorithm, of which I will give an explanation. Also some
  389.       details of how it is speeded up further wil be given.
  390.       The algorithm consists of taking always a step in the direction of the
  391.       axis of greatest movement, and, depending on an accumulating error term
  392.       also in the direction of smallest movement. A derivation for the simple
  393.       case that the start point is (0,0) and the end point (a,b) with a >= b
  394.       and a and b both >= 0:
  395.       Equation of the line:
  396.  
  397.                  a . y - b . x = 0                             (1)
  398.  
  399.       Now take (x(n), y(n)) to be the nth point of the line. Because x(n) and
  400.       y(n) are integers, they will generally not satisfy (1). In fact an error
  401.       term d(n) exists, generally not 0:
  402.  
  403.                  a . y(n)  - b . x(n)  = d(n)                  (2)
  404.  
  405.       Since steps are to be taken in x direction, the x(n) is 'correct';
  406.       the y(n) may be off at most 0.5, so
  407.  
  408.                  - 0.5a <= d(n) < 0.5a.                        (3)
  409.  
  410.       It is easier to compare against 0, so instead of d(n) we use e(n) with
  411.  
  412.                  e(n) = d(n) + 0.5a.                           (4)
  413.  
  414.       and
  415.  
  416.                  0 <= e(n) < a                                 (5)
  417.  
  418.       By subtracting (2) from (2) with n+1 instead of n we get:
  419.  
  420.                  a . (y(n+1) - y(n)) - b . (x(n+1) - x(n))  = d(n+1) - d(n)
  421.  
  422.       Since x(n+1) - x(n) == 1, and d(n+1) - d(n) == e(n+1) - e(n):
  423.  
  424.                  a . (y(n+1) - y(n)) - b = e(n+1) - e(n), or
  425.  
  426.                  e(n+1) = e(n) - b + a . (y(n+1) - y(n))       (6)
  427.  
  428.       Now it's easy, since the e(n+1) must be >= 0  (5), and y(n+1) - y(n)
  429.       is either 1 or 0:
  430.       subtract b from e(n); if result < 0 increment y and add a to error term.
  431.  
  432.       In a C program:
  433.  
  434.       short x,y,a,b,e;
  435.  
  436.       e = a >> 1; /* d(0) == 0, so e(0) == 0.5a */
  437.       y = 0;
  438.  
  439.       for (x = 0; x <= a; x++) {
  440.          plot(x,y);
  441.          if ((e -= b ) < 0) {
  442.             y++;
  443.             e += a;
  444.          }
  445.       }
  446.  
  447.       The 'real' thing must also handle the other cases: b > a, a < 0 or
  448.       b < 0:
  449.       First end and starting point are swapped if x2 < x1, so that always
  450.       x2 >= x1; this implies a > 0. The increment of y is 1 if b >= 0,
  451.       -1 if b < 0 and furthermore b is then set to its absolute value.
  452.       The cases a >= b and b > a are dealt with separately.
  453.       Because the machine addresses bytes, not bits, and thus in order to
  454.       avoid excessive address calculations, the pixel (x,y) is represented
  455.       by a word address and a bit in that word. Stepping in x direction is
  456.       done by rotating the word by 1, incrementing/decrementing the address
  457.       if a carry is generated. Stepping in y direction is done by
  458.       adding/subtracting the number_of_bytes_per_line to the address
  459.       (effectively stepping a line).
  460.       The new point is OR-ed into the screen each time; in fact, this OR-ing
  461.       is done into a data register for speed; the actual storing into the
  462.       screen is done when the address is about to change. In the case that
  463.       b > a, the y-step is always taken, so the OR-ing into the data reg. is
  464.       NOT done there.
  465.       An even faster version of drawlin is being planned, but implementing
  466.       it would postpone the current distribution. Next release!
  467.  
  468.    From object.c:
  469.  
  470.    o  item matcrit(n,d,o)
  471.       int n;              I  the point count
  472.       double d[][3];      I  the n*3 coordinates of the points
  473.       short *o;           I  an array of indexes for the points; each -1 value
  474.                              ends a joined set of points, an extra -1 ends the
  475.                              array.
  476.  
  477.       Create an item by giving its point count, point coordinates and order.
  478.       The function allocates memory for the item, in this it stores the point
  479.       count, the points homogeneous 4D coordinates and a polygon list pointer.
  480.       For each polygon also memory is allocated to contain a count and an
  481.       array of indices.
  482.  
  483.    o  void matfrit(ip)
  484.       item ip;            I  item to be freed
  485.  
  486.       Frees all memory belonging to the item that was allocated by matcrit.
  487.  
  488.    o  instance matcrins(it,lia,tv)
  489.       item it;            I  the item it's refering to.
  490.       double lia[3][3];   I  the 3x3 transformation array.
  491.       double tv[3];       I  the translation vector.
  492.  
  493.       Create an instance of the item by giving the item and a transformation
  494.       matrix to put it into space. Note that the transformation array is an
  495.       array of 3x3 doubles (non-homogeneous coordinates), and also the
  496.       translation vector is in non-homogeneous coordinates. The memory
  497.       allocated will contain a pointer to the item, a 4H to place the item
  498.       in space, and an array to hold the screen coordinates of each point of
  499.       the instance.
  500.  
  501.    o  void matfrins(ins)
  502.       instance ins;       I  instance to be freed
  503.  
  504.       Frees all memory belonging to the instance that was allocated by
  505.       matcrins.
  506.  
  507.    o  WORD *matseteye(lia,tv,dist,sx,sy)
  508.       double lia[3][3];   I  the transformation to orientate the screen
  509.       double tv[3];       I  the vector to place the screen
  510.       double dist;        I  the distance of the eye from the proj. screen
  511.       double sx,sy;       I  scaling for X-, resp. Y-axis.
  512.  
  513.       Fix the eye and projection screen positions and orientations and scaling.
  514.       This generally has to be done once, unless the eye or proj. screen are
  515.       moving.
  516.  
  517.    o  void matproject(ins)
  518.       register instance ins; I  the instance to be projected.
  519.  
  520.       Project an instance, i.e. calculate the screen coordinates it will need
  521.       to draw it. This will fill the array of screen coordinates within the
  522.       instance with values that depend on the current contents of the
  523.       instance's 4H transformation and the observer's position (set by
  524.       matseteye). The critical part is handled by mxproj for speed reasons.
  525.  
  526.    o  void matdraw(ins,mode)
  527.       instance ins;       I  the instance to be drawn.
  528.       int mode;           I  the mode of drawing (OR,XOR,ERASE etc.)
  529.  
  530.       Draw an instance, using VDI. Each polygon in the instance's item's
  531.       polygon list is drawn, using the coordinates in the instances screen
  532.       coordinates array.
  533.  
  534.    o  void matfdraw(ins,mode)
  535.       instance ins;       I  the instance to be drawn.
  536.       int mode;           I  the mode of drawing (OR,XOR,ERASE etc.)
  537.  
  538.       Draw an instance, using drawlin. The mode parameter is currently ignored.
  539.       See also matdraw. This method is faster; an even faster method for
  540.       drawing lines than drawlin is planned.
  541.  
  542.    o  void insstore(ins,a,n)      stores
  543.       instance ins;       I  into
  544.       WORD *a;            O  as entry number
  545.       int n;              I  ; i.e. there are n WORDs in a preceding.
  546.  
  547.       Store the calculated screenpoints of an instance.
  548.       The screen coordinates are stored in a as a[n], a[n+1] etc.
  549.       In this way line images can be stored with minimum overhead. The only
  550.       processing that needs to be done afterwards is calling insload and
  551.       matfdraw (or matdraw). Before insstore is called the coordinate array
  552.       has to be calculated, preferably with matproject.
  553.  
  554.    o  void insload(ins,a,n)    loads
  555.       instance ins;       I  from
  556.       WORD *a;            I  as entry number
  557.       int n;              I  ; i.e. there are n WORDs in a preceding.
  558.  
  559.       Recall the calculated screenpoints of an instance. See also insstore.
  560.  
  561.    o  static WORD *matliatv(invers,lia,tv,rotra)
  562.       int invers;         I  Use inverse of lin. transf.
  563.       double lia[3][3],   I  Linear transform. to place it
  564.              tv[3];       I  Translation vector to place it
  565.       WORD *rotra;        O  4H result
  566.  
  567.       Apply linear transformation and translation. Note that this function is
  568.       static and can thus not be used as external function. Use matapply for
  569.       a function with comparable capabilities; the difference is that
  570.       matliatv can specify all kinds of linear transformations, and that it
  571.       puts the result in rotra, while matapply is restricted to translation,
  572.       rotation and reflection and applies the thus created 4H upon the output
  573.       4H.
  574.  
  575.    o  WORD *matseteye(lia,tv,dist,sx,sy)
  576.       double lia[3][3],   I  Linear transform. to place it
  577.              tv[3],       I  Translation vector to place it
  578.              dist,        I  Distance eye from screen
  579.              sx,sy;       I  Scaling x and y axis
  580.  
  581.       Set eye coordinates. Besides setting distance and scaling the function
  582.       returns a pointer to the (static) 4H observer matrix.
  583.